package com.cuit.springboot.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 
 * @author greenli
 * 
 */
@SuppressWarnings("all")
public class DateUtil
{

	/**
     * date2比date1多的天数
     * @param date1    
     * @param date2
     * @return    
     */
    public static int differentDays(Date date1,Date date2)
    {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
       int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);
        
        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2)   //同一年
        {
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0)    //闰年            
                {
                    timeDistance += 366;
                }
                else    //不是闰年
                {
                    timeDistance += 365;
                }
            }
            
            return timeDistance + (day2-day1) ;
        }
        else    //不同年
        {
            //System.out.println("判断day2 - day1 : " + (day2-day1));
            return day2-day1;
        }
    }
	/**
	 * 把字符串转化成日期型。
	 * 
	 * 字符串 日期格式
	 * 
	 * @return Date 转化后的日期
	 */
	public static Date getDate(String name, String df, Date defaultValue)
	{
		if (name == null)
		{
			return defaultValue;
		}

		SimpleDateFormat formatter = new SimpleDateFormat(df);

		try
		{
			return formatter.parse(name);
		}
		catch (ParseException e)
		{
		}

		return defaultValue;
	}

	/**
	 * 把字符串转化成日期型。 缺省为当前系统时间。
	 * 
	 * 字符串
	 */
	public static Date getDate(String name)
	{
		return getDate(name, null);
	}

	/**
	 * 把字符串转化成日期型。 缺省为当前系统时间。
	 * 
	 * 字符串
	 */
	public static Date getDateTime(String name)
	{
		return getDateTime(name, null);
	}
	/**
	 * 把字符串转化成日期型。
	 */
	public static Date getDateTimeForReport(String d)
	{
		Date date=getDateTime(d);
		if(date==null)
			date=getDate(d);
		if(date==null)
			date=getDate(d, "yyyy/MM/dd", null);
					
		return date;
	}

	/**
	 * 把字符串转化成日期型。
	 * 
	 * 字符串 日期格式
	 * 
	 * @return Date 转化后的日期
	 */
	public static Date getDate(String name, Date defaultValue)
	{
		return getDate(name, "yyyy-MM-dd", defaultValue);
	}

	/**
	 * 把字符串转化成日期型。
	 * 
	 * 字符串 日期格式
	 * 
	 * @return Date 转化后的日期
	 */
	public static Date getDateTime(String name, Date defaultValue)
	{
		return getDate(name, "yyyy-MM-dd HH:mm:ss", defaultValue);
	}

	public static Date mysqlDate2Date(int seconds)
	{
		long l = (long) seconds * 1000;
		Date date = new Date(l);
		return date;
	}

	public static long date2MysqlDate(Date date)
	{
		return date.getTime() / 1000;
	}

	/**
	 * 返回两个日期的时间差，返回的时间差格式可以是: Calendar.YEAR, Calendar.MONTH, Calendar.DATE
	 * 注意：该功能采用递归的方法，效率还有待解决，如果两个时间之差较大，而要求返回的时间格式又很小，这时效率就很差
	 * 但此方法在要求精度较高的情况下比较有效，如求月份差的时候就比较准确，考虑到了各种情况．如闰月，闰年
	 * 
	 * @param earlyDate
	 * @param lateDate
	 * @param returnTimeFormat
	 * @return time
	 */
	public static int getBetweenTime(Calendar earlyDate, Calendar lateDate, int returnTimeFormat)
	{
		earlyDate = (Calendar) earlyDate.clone();
		lateDate = (Calendar) lateDate.clone();
		int time = 0;
		while (earlyDate.before(lateDate))
		{
			earlyDate.add(returnTimeFormat, 1);
			time++;
		}
		return time;
	}

	public static int getBetweenYear(Date lastDate)
	{
		int between = Integer.MIN_VALUE;
		if (lastDate != null)
		{
			Calendar cnow = Calendar.getInstance();
			Calendar clast = Calendar.getInstance();
			clast.setTime(lastDate);
			between = getBetweenTime(clast, cnow, Calendar.YEAR);
		}
		return between;
	}

	/**
	 * 求两个日期相差天数
	 * 
	 * @param sd
	 *                起始日期，格式yyyy-MM-dd
	 * @param ed
	 *                终止日期，格式yyyy-MM-dd
	 * @return 两个日期相差天数
	 */
	public static long getBetweenDay(String sd, String ed)
	{
		return ((java.sql.Date.valueOf(ed)).getTime() - (java.sql.Date.valueOf(sd))
		                .getTime()) / (3600 * 24 * 1000);
	}

	/**
	 * 求两个日期相差天数
	 * 
	 * @param sd
	 *                起始日期，格式yyyy-MM-dd
	 * @param ed
	 *                终止日期，格式yyyy-MM-dd
	 * @return 两个日期相差天数
	 */
	public static long getBetweenDay(Date sd, Date ed)
	{
		return (ed.getTime() - sd.getTime()) / (3600 * 24 * 1000);
	}

	public static int getBetweenDay(Date lastDate)
	{
		int between = Integer.MIN_VALUE;
		if (lastDate != null)
		{
			Calendar cnow = Calendar.getInstance();
			Calendar clast = Calendar.getInstance();
			clast.setTime(lastDate);
			between = getBetweenTime(clast, cnow, Calendar.DATE);
		}
		return between;
	}

	/**
	 * 得到给定的时间距离现在的天数
	 * 
	 * @param last
	 * @return
	 */
	public static int getBetweenDays(int last)
	{
		Calendar cnow = Calendar.getInstance();
		Calendar clast = Calendar.getInstance();
		clast.setTime(DateUtil.mysqlDate2Date(last));
		int between = getBetweenTime(clast, cnow, Calendar.DATE);
		return between;
	}

	public static String dateFormate(Date date, String formate)
	{
		if (date != null)
		{
			SimpleDateFormat sdf = new SimpleDateFormat(formate);
			return sdf.format(date);
		}
		else
		{
			return null;
		}

	}

	public static String dateFormateHuman(int seconds)
	{
		Date date = DateUtil.mysqlDate2Date(seconds);

		Calendar cnow = Calendar.getInstance();
		Calendar clast = Calendar.getInstance();
		cnow.setTime(new Date());
		clast.setTime(date);
		String format = "";
		if (cnow.get(Calendar.YEAR) == clast.get(Calendar.YEAR)
		                && cnow.get(Calendar.MONTH) == clast.get(Calendar.MONTH)
		                && cnow.get(Calendar.DATE) == clast.get(Calendar.DATE))
		{
			format = "HH:mm";
		}
		else if (cnow.get(Calendar.YEAR) == clast.get(Calendar.YEAR)
		                && cnow.get(Calendar.MONTH) == clast.get(Calendar.MONTH))
		{
			format = "MM月dd日";
		}
		else
		{
			format = "yyyy年MM月dd日";
		}

		return dateFormate(date, format);
	}

	public static String dateFormate(int seconds, String formate)
	{
		Date date = DateUtil.mysqlDate2Date(seconds);
		return dateFormate(date, formate);
	}

	public static Date getTime(String name, Date defaultValue)
	{
		return getDate(name, "HH:mm:ss", defaultValue);
	}

	public static Date getTime(String name)
	{
		return getTime(name, null);
	}
	public static Date getTimehhmm(String name, Date defaultValue)
	{
		return getDate(name, "HH:mm", defaultValue);
	}

	/**
	 * 比较日期值对应的时间与字符串对应的时间值的大小(只比较HH:mm:ss部分)。
	 * 
	 * @param dateTime
	 *                日期值
	 * @param timeString
	 *                时间字符串
	 * @return <br>
	 *         dateTime的时间早于 timeString的时间则返回 -1;<br>
	 *         dateTime的时间晚于 timeString的时间则返回 1;<br>
	 *         dateTime的时间等于 timeString的时间则返回 0;
	 */
	public static int dateTimeDiff(Date dateTime, String timeString)
	{
		Calendar dTime = Calendar.getInstance();
		Calendar sTime = Calendar.getInstance();
		dTime.setTime(dateTime);
		sTime.setTime(getTime(timeString));
		sTime.set(Calendar.YEAR, dTime.get(Calendar.YEAR));
		sTime.set(Calendar.MONTH, dTime.get(Calendar.MONTH));
		sTime.set(Calendar.DATE, dTime.get(Calendar.DATE));
		if (dTime.before(sTime))
		{
			return -1;
		}
		if (dTime.after(sTime))
		{
			return 1;
		}
		return 0;
	}

	public static Date rollDate(Date dateTime, int field, int amount)
	{
		if (dateTime != null)
		{
			Calendar c = Calendar.getInstance();
			c.setTime(dateTime);
			c.add(field, amount);
			return c.getTime();
		}
		return null;
	}

	/**
	 * 功能：计算日期 作者：chendw 时间：2010-3-4 下午07:47:31 版本： 参数： 日期基值 date 计算类型 type
	 * 如 Calendar.YEAR、Calendar.MONTH 计算偏值 num
	 * 
	 * @return
	 */
	public static Date caclDate(Date date, int type, int num)
	{
		Calendar C = Calendar.getInstance();
		C.setTime(date);
		C.add(type, num);
		return C.getTime();
	}

	public static String dateTostring(Date date, String typ)
	{
		String sdate = (new SimpleDateFormat(typ)).format(date);
		return sdate;
	}

	

	private  static String[] splitDataKey(String datakey)
	{
		String[] datakeyArry = new String[3];
		// String newStr = str.replaceFirst("^0*",
		// "");System.out.println(newStr);
		datakeyArry[0] = datakey.substring(2, 18).replaceAll("^(0+)", "");
		datakeyArry[1] = datakey.substring(18, 34);
		datakeyArry[2] = datakey.substring(34, 54).replaceAll("^(0+)", "");
		if (datakeyArry[2].length() > 15)
		{
			datakeyArry[2] = datakeyArry[2].substring(0, 15);
		}
		return datakeyArry;
	}

	public Date getLastYearDate()
	{
		java.util.Date todayDate = new java.util.Date();
		long beforeTime = (todayDate.getTime() / 1000) - 60 * 60 * 24 * 365;
		return new java.util.Date(beforeTime * 1000);
	}

	public Date getTimeSolt(int time)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, 1 - time);
		// 将小时至0
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		// 将分钟至0
		calendar.set(Calendar.MINUTE, 0);
		// 将秒至0
		calendar.set(Calendar.SECOND, 0);
		// 将毫秒至0
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public Date getTimeByYearOfLast(int time)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.YEAR, 1 - time);
		// 将小时至0
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		// 将分钟至0
		calendar.set(Calendar.MINUTE, 0);
		// 将秒至0
		calendar.set(Calendar.SECOND, 0);
		// 将毫秒至0
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 根据时间段获取所有日期
	 * 
	 * @param dBegin
	 * @param dEnd
	 * @return
	 */
	public static List<Date> getYearCalendar(Date dBegin, Date dEnd)
	{
		List<Date> lDate = new ArrayList<Date>();
		lDate.add(dBegin);
		Calendar calBegin = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calBegin.setTime(dBegin);
		Calendar calEnd = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calEnd.setTime(dEnd);
		// 测试此日期是否在指定日期之后
		while (dEnd.after(calBegin.getTime()))
		{
			// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
			calBegin.add(Calendar.DAY_OF_MONTH, 1);
			lDate.add(calBegin.getTime());
		}
		return lDate;
	}

	/**
	 * 获取当年的最后一天
	 * 
	 * @return
	 */
	public static Date getCurrYearLast()
	{
		Calendar currCal = Calendar.getInstance();
		int currentYear = currCal.get(Calendar.YEAR);
		return getYearLast(currentYear);
	}

	/**
	 * 获取当年的第一天
	 * 
	 * @return
	 */
	public static Date getCurrYearFirst()
	{
		Calendar currCal = Calendar.getInstance();
		int currentYear = currCal.get(Calendar.YEAR);
		return getYearFirst(currentYear);
	}

	/**
	 * 获取某年最后一天日期
	 * 
	 * @param year
	 *                年份
	 * @return Date
	 */
	public static Date getYearLast(int year)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.roll(Calendar.DAY_OF_YEAR, -1);
		Date currYearLast = calendar.getTime();

		return currYearLast;
	}

	/**
	 * 获取某年第一天
	 * 
	 * @param year
	 * @return
	 */
	public static Date getYearFirst(int year)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		Date currYearFirst = calendar.getTime();
		return currYearFirst;
	}

	/**
	 * 获取今天是周几
	 * 
	 * @param dt
	 * @return
	 */
	public static String getWeekOfDate(Date dt)
	{
		String []weeString=new String[]{"周日","周一","周二","周三","周四","周五","周六"};
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0)
		{
			w = 0;
		}
		return weeString[w];
	}
	
	/**
	 * 获取今天是周几 int 1-7
	 * 
	 * @param dt
	 * @return
	 */
	public static int getWeekOfDateInt(Date dt)
	{
		Integer []weeString=new Integer[]{7,1,2,3,4,5,6};
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0)
		{
			w = 0;
		}
		return weeString[w];
	}

	/**
	 * 当前日期增加n天日期
	 * 
	 * @param date
	 * @param num
	 * @return
	 */
	public static Date getDateAdd(Date date, int num)
	{
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_MONTH, num);
		return c.getTime();
	}

	/**
	 * 获取指定日期 前 n天的日期
	 * 
	 * @param date
	 *                指定的日期
	 * @param num
	 *                指定日期前 num天
	 * @return 返回前n天的日期
	 */
	public static Date getSpecifiedDayBefore(Date date, int num)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int day = c.get(Calendar.DATE);
		c.set(Calendar.DATE, day - num);
		return c.getTime();
	}

	/**
	 * 获取指定日期 后 n天的日期
	 * 
	 * @param date
	 *                指定的日期
	 * @param num
	 *                指定日期后 num天
	 * @return 返回后n天的日期
	 */
	public static Date getSpecifiedDayAfter(Date date, int num)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int day = c.get(Calendar.DATE);
		c.set(Calendar.DATE, day + num);
		return c.getTime();
	}
	
	/**
	 * 根据用户生日计算年龄
	 */
	public static int getAgeByBirthday(Date birthday) {
		Calendar cal = Calendar.getInstance();

		if(birthday==null)
			return 0;

		int yearNow = cal.get(Calendar.YEAR);
		int monthNow = cal.get(Calendar.MONTH) + 1;
		int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

		cal.setTime(birthday);
		int yearBirth = cal.get(Calendar.YEAR);
		int monthBirth = cal.get(Calendar.MONTH) + 1;
		int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

		int age = yearNow - yearBirth;

		if (monthNow <= monthBirth) {
			if (monthNow == monthBirth) {
				// monthNow==monthBirth 
				if (dayOfMonthNow < dayOfMonthBirth) {
					age--;
				}
			} else {
				// monthNow>monthBirth 
				age--;
			}
		}
		if(age<=0)
			return 0;
		return age;
	}
	/**
	 * 根据用户出生年份计算年龄 相对真实年龄偏大
	 */
	public static int getAgeByYear(Date birthday) {
		Calendar cal = Calendar.getInstance();

		if(birthday==null)
			return 0;
		int yearNow = cal.get(Calendar.YEAR);
		cal.setTime(birthday);
		int yearBirth = cal.get(Calendar.YEAR);
		int age = yearNow - yearBirth;
		return age;
	}
	/**
	 * add by xuji at  2016-9-3
	 * 判断日期是否在给定开始结束日期之间 包含首尾
	 */
	public static boolean isBetween(Date datestart,Date dateend,Date datenow)
	{
		Calendar cal1=Calendar.getInstance();
		cal1.setTime(datestart);
		Calendar cal2=Calendar.getInstance();
		cal2.setTime(dateend);
		Calendar cal3=Calendar.getInstance();
		cal3.setTime(datenow);
		if((cal1.before(cal3)||cal1.equals(cal3))&&(cal2.after(cal3)||cal2.equals(cal3)))
			return true;
		return false;
	}
	
	/**
	 * add by wanglei at 2018-2-2 下午5:47:26
	 * 判断日期是否在给定开始结束日期之间 不包含尾
	 */
	public static boolean isBetweenWithOutEnd(Date datestart,Date dateend,Date datenow)
	{
		Calendar cal1=Calendar.getInstance();
		cal1.setTime(datestart);
		Calendar cal2=Calendar.getInstance();
		cal2.setTime(dateend);
		Calendar cal3=Calendar.getInstance();
		cal3.setTime(datenow);
		if((cal1.before(cal3)||cal1.equals(cal3))&&cal2.after(cal3))
			return true;
		return false;
	}
	
	public static boolean isBefore(Date datebefore,Date datenow)
	{
		Calendar before=Calendar.getInstance();
		before.setTime(datebefore);
		Calendar now=Calendar.getInstance();
		now.setTime(datenow);
		if(now.before(before))
			return true;
		return false;
	}
	
	public static boolean isAfter(Date dateafter,Date datenow)
	{
		Calendar after=Calendar.getInstance();
		after.setTime(dateafter);
		Calendar now=Calendar.getInstance();
		now.setTime(datenow);
		if(now.after(after))
			return true;
		return false;
	}
	
	public static String getDate(Date date,String pattren) {
		SimpleDateFormat format=new SimpleDateFormat(pattren);
		if(date!=null){
			return format.format(date);
		}else {
			return "";
		}
	}
	 /**
     * 当月第一天
     * @return
     */
	public static Date getMonthFirst(int year,int month) {
    	Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month-1);
		Date currYearFirst = calendar.getTime();
		return currYearFirst;
    }
    
    /**
     * 当月最后一天
     * @return
     */
    public static Date getMonthLast(int year,int month) {		
		// 获取Calendar  
		Calendar calendar = Calendar.getInstance();  
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		// 设置Calendar月份数为下一个月  
		calendar.set(Calendar.MONTH, month-1 + 1);  
		// 设置Calendar日期为下一个月一号  
		calendar.set(Calendar.DATE, 1);  
		// 设置Calendar日期减一,为本月末  
		calendar.add(Calendar.SECOND, -1); 
		Date currYearLast = calendar.getTime();
		return currYearLast;

    }
    
    public static Date addYear(Date date,int year){
    	Calendar calendar=Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.add(Calendar.YEAR, year);
    	return calendar.getTime();
    }
    
    public static int getMonthFromDate(Date date){
    	Calendar calendar=Calendar.getInstance();
    	calendar.setTime(date);
    	return calendar.get(Calendar.MONTH);
    }
    
    public static Date getDateFromDateAndTime(Date yyyyMMdd,Date dateHHmm){
    	Calendar c1=Calendar.getInstance();
    	c1.setTime(dateHHmm);   	
    	Calendar c2=Calendar.getInstance();
    	c2.setTime(yyyyMMdd);
    	c2.set(Calendar.HOUR_OF_DAY, c1.get(Calendar.HOUR_OF_DAY));
    	c2.set(Calendar.MINUTE, c1.get(Calendar.MINUTE));
    	c2.set(Calendar.SECOND, 0);
    	return c2.getTime();
    }
    
	public static void main(String[] agrs)
	{
//		System.out.println(splitDataKey("020000000000001082050320135225050500002410000878500000")[2]);
//		Date date1=new Date();
//		
//		TimeZone timeZone=TimeZone.getTimeZone("UTC");
//		System.out.println(Calendar.getInstance().getTimeZone().getDisplayName());
//		System.out.println(timeZone.getDisplayName());
//		System.out.println(date1);
//		String idcard="330724711126161";
//		IdcardInfoExtractor idcardInfoExtractor=new IdcardInfoExtractor(idcard);
//		
//		System.out.println(idcardInfoExtractor.getBirthday());
//		System.out.println(getAgeByBirthday(idcardInfoExtractor.getBirthday()));
//		Date date1=getDateTime("2016-11-01 16:47:01");
//		Date date2=getDateTime("2016-11-01 16:47:01");
//		if(date1.equals(date2))
//			System.out.println("ok");
//		System.out.println(dateTostring(getMonthFirst(2017, 2), "yyyy-MM-dd HH:mm:ss"));
//		System.out.println(dateTostring(getMonthLast(2017, 2),"yyyy-MM-dd HH:mm:ss"));
//		System.out.println(getDateTimeForReport(""));
		
		/*Date date=new Date();
		System.out.println(getMonthFromDate(date));*/
		//System.out.println(getDateFromDateAndTime(new Date(), getTimehhmm("12:00", null)));
		//System.err.println(isBetween(getDate("2018-1-16 08:00:00"), getDate("2018-1-16 09:00:00"), getDate("2018-1-16 08:00:00")));
		Date d1=DateUtil.getDateTime("2018-09-24 07:09:07");
		Date d2=DateUtil.getDateTime("2018-09-27 07:09:07");
		System.out.println(DateUtil.getBetweenDay(d1, d2));
	}
}
//}
